1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkElementIndex;
21 import static com.google.common.base.Preconditions.checkNotNull;
22
23 import com.google.common.annotations.Beta;
24 import com.google.common.annotations.GwtCompatible;
25 import com.google.common.annotations.GwtIncompatible;
26 import com.google.common.base.Objects;
27
28 import java.io.Serializable;
29 import java.lang.reflect.Array;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36
37 import javax.annotation.Nullable;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 @Beta
85 @GwtCompatible(emulated = true)
86 public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements Serializable {
87
88
89
90
91
92
93
94
95
96
97 public static <R, C, V> ArrayTable<R, C, V> create(
98 Iterable<? extends R> rowKeys, Iterable<? extends C> columnKeys) {
99 return new ArrayTable<R, C, V>(rowKeys, columnKeys);
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 public static <R, C, V> ArrayTable<R, C, V> create(Table<R, C, V> table) {
131 return (table instanceof ArrayTable<?, ?, ?>)
132 ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
133 : new ArrayTable<R, C, V>(table);
134 }
135
136 private final ImmutableList<R> rowList;
137 private final ImmutableList<C> columnList;
138
139
140 private final ImmutableMap<R, Integer> rowKeyToIndex;
141 private final ImmutableMap<C, Integer> columnKeyToIndex;
142 private final V[][] array;
143
144 private ArrayTable(Iterable<? extends R> rowKeys,
145 Iterable<? extends C> columnKeys) {
146 this.rowList = ImmutableList.copyOf(rowKeys);
147 this.columnList = ImmutableList.copyOf(columnKeys);
148 checkArgument(!rowList.isEmpty());
149 checkArgument(!columnList.isEmpty());
150
151
152
153
154
155
156 rowKeyToIndex = index(rowList);
157 columnKeyToIndex = index(columnList);
158
159 @SuppressWarnings("unchecked")
160 V[][] tmpArray
161 = (V[][]) new Object[rowList.size()][columnList.size()];
162 array = tmpArray;
163
164 eraseAll();
165 }
166
167 private static <E> ImmutableMap<E, Integer> index(List<E> list) {
168 ImmutableMap.Builder<E, Integer> columnBuilder = ImmutableMap.builder();
169 for (int i = 0; i < list.size(); i++) {
170 columnBuilder.put(list.get(i), i);
171 }
172 return columnBuilder.build();
173 }
174
175 private ArrayTable(Table<R, C, V> table) {
176 this(table.rowKeySet(), table.columnKeySet());
177 putAll(table);
178 }
179
180 private ArrayTable(ArrayTable<R, C, V> table) {
181 rowList = table.rowList;
182 columnList = table.columnList;
183 rowKeyToIndex = table.rowKeyToIndex;
184 columnKeyToIndex = table.columnKeyToIndex;
185 @SuppressWarnings("unchecked")
186 V[][] copy = (V[][]) new Object[rowList.size()][columnList.size()];
187 array = copy;
188
189 eraseAll();
190 for (int i = 0; i < rowList.size(); i++) {
191 System.arraycopy(table.array[i], 0, copy[i], 0, table.array[i].length);
192 }
193 }
194
195 private abstract static class ArrayMap<K, V> extends Maps.ImprovedAbstractMap<K, V> {
196 private final ImmutableMap<K, Integer> keyIndex;
197
198 private ArrayMap(ImmutableMap<K, Integer> keyIndex) {
199 this.keyIndex = keyIndex;
200 }
201
202 @Override
203 public Set<K> keySet() {
204 return keyIndex.keySet();
205 }
206
207 K getKey(int index) {
208 return keyIndex.keySet().asList().get(index);
209 }
210
211 abstract String getKeyRole();
212
213 @Nullable abstract V getValue(int index);
214
215 @Nullable abstract V setValue(int index, V newValue);
216
217 @Override
218 public int size() {
219 return keyIndex.size();
220 }
221
222 @Override
223 public boolean isEmpty() {
224 return keyIndex.isEmpty();
225 }
226
227 @Override
228 protected Set<Entry<K, V>> createEntrySet() {
229 return new Maps.EntrySet<K, V>() {
230 @Override
231 Map<K, V> map() {
232 return ArrayMap.this;
233 }
234
235 @Override
236 public Iterator<Entry<K, V>> iterator() {
237 return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
238 @Override
239 protected Entry<K, V> get(final int index) {
240 return new AbstractMapEntry<K, V>() {
241 @Override
242 public K getKey() {
243 return ArrayMap.this.getKey(index);
244 }
245
246 @Override
247 public V getValue() {
248 return ArrayMap.this.getValue(index);
249 }
250
251 @Override
252 public V setValue(V value) {
253 return ArrayMap.this.setValue(index, value);
254 }
255 };
256 }
257 };
258 }
259 };
260 }
261
262
263
264 @Override
265 public boolean containsKey(@Nullable Object key) {
266 return keyIndex.containsKey(key);
267 }
268
269 @Override
270 public V get(@Nullable Object key) {
271 Integer index = keyIndex.get(key);
272 if (index == null) {
273 return null;
274 } else {
275 return getValue(index);
276 }
277 }
278
279 @Override
280 public V put(K key, V value) {
281 Integer index = keyIndex.get(key);
282 if (index == null) {
283 throw new IllegalArgumentException(
284 getKeyRole() + " " + key + " not in " + keyIndex.keySet());
285 }
286 return setValue(index, value);
287 }
288
289 @Override
290 public V remove(Object key) {
291 throw new UnsupportedOperationException();
292 }
293
294 @Override
295 public void clear() {
296 throw new UnsupportedOperationException();
297 }
298 }
299
300
301
302
303
304 public ImmutableList<R> rowKeyList() {
305 return rowList;
306 }
307
308
309
310
311
312 public ImmutableList<C> columnKeyList() {
313 return columnList;
314 }
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330 public V at(int rowIndex, int columnIndex) {
331
332 checkElementIndex(rowIndex, rowList.size());
333 checkElementIndex(columnIndex, columnList.size());
334 return array[rowIndex][columnIndex];
335 }
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 public V set(int rowIndex, int columnIndex, @Nullable V value) {
353
354 checkElementIndex(rowIndex, rowList.size());
355 checkElementIndex(columnIndex, columnList.size());
356 V oldValue = array[rowIndex][columnIndex];
357 array[rowIndex][columnIndex] = value;
358 return oldValue;
359 }
360
361
362
363
364
365
366
367
368
369
370
371 @GwtIncompatible("reflection")
372 public V[][] toArray(Class<V> valueClass) {
373
374 @SuppressWarnings("unchecked")
375 V[][] copy = (V[][]) Array.newInstance(
376 valueClass, new int[] { rowList.size(), columnList.size() });
377 for (int i = 0; i < rowList.size(); i++) {
378 System.arraycopy(array[i], 0, copy[i], 0, array[i].length);
379 }
380 return copy;
381 }
382
383
384
385
386
387
388
389 @Override
390 @Deprecated public void clear() {
391 throw new UnsupportedOperationException();
392 }
393
394
395
396
397
398 public void eraseAll() {
399 for (V[] row : array) {
400 Arrays.fill(row, null);
401 }
402 }
403
404
405
406
407
408 @Override
409 public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
410 return containsRow(rowKey) && containsColumn(columnKey);
411 }
412
413
414
415
416
417 @Override
418 public boolean containsColumn(@Nullable Object columnKey) {
419 return columnKeyToIndex.containsKey(columnKey);
420 }
421
422
423
424
425
426 @Override
427 public boolean containsRow(@Nullable Object rowKey) {
428 return rowKeyToIndex.containsKey(rowKey);
429 }
430
431 @Override
432 public boolean containsValue(@Nullable Object value) {
433 for (V[] row : array) {
434 for (V element : row) {
435 if (Objects.equal(value, element)) {
436 return true;
437 }
438 }
439 }
440 return false;
441 }
442
443 @Override
444 public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
445 Integer rowIndex = rowKeyToIndex.get(rowKey);
446 Integer columnIndex = columnKeyToIndex.get(columnKey);
447 return (rowIndex == null || columnIndex == null)
448 ? null : at(rowIndex, columnIndex);
449 }
450
451
452
453
454 @Override
455 public boolean isEmpty() {
456 return false;
457 }
458
459
460
461
462
463
464
465 @Override
466 public V put(R rowKey, C columnKey, @Nullable V value) {
467 checkNotNull(rowKey);
468 checkNotNull(columnKey);
469 Integer rowIndex = rowKeyToIndex.get(rowKey);
470 checkArgument(rowIndex != null, "Row %s not in %s", rowKey, rowList);
471 Integer columnIndex = columnKeyToIndex.get(columnKey);
472 checkArgument(columnIndex != null,
473 "Column %s not in %s", columnKey, columnList);
474 return set(rowIndex, columnIndex, value);
475 }
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493 @Override
494 public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
495 super.putAll(table);
496 }
497
498
499
500
501
502
503
504 @Override
505 @Deprecated public V remove(Object rowKey, Object columnKey) {
506 throw new UnsupportedOperationException();
507 }
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522 public V erase(@Nullable Object rowKey, @Nullable Object columnKey) {
523 Integer rowIndex = rowKeyToIndex.get(rowKey);
524 Integer columnIndex = columnKeyToIndex.get(columnKey);
525 if (rowIndex == null || columnIndex == null) {
526 return null;
527 }
528 return set(rowIndex, columnIndex, null);
529 }
530
531
532
533 @Override
534 public int size() {
535 return rowList.size() * columnList.size();
536 }
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551 @Override
552 public Set<Cell<R, C, V>> cellSet() {
553 return super.cellSet();
554 }
555
556 @Override
557 Iterator<Cell<R, C, V>> cellIterator() {
558 return new AbstractIndexedListIterator<Cell<R, C, V>>(size()) {
559 @Override protected Cell<R, C, V> get(final int index) {
560 return new Tables.AbstractCell<R, C, V>() {
561 final int rowIndex = index / columnList.size();
562 final int columnIndex = index % columnList.size();
563 @Override
564 public R getRowKey() {
565 return rowList.get(rowIndex);
566 }
567 @Override
568 public C getColumnKey() {
569 return columnList.get(columnIndex);
570 }
571 @Override
572 public V getValue() {
573 return at(rowIndex, columnIndex);
574 }
575 };
576 }
577 };
578 }
579
580
581
582
583
584
585
586
587
588
589
590
591
592 @Override
593 public Map<R, V> column(C columnKey) {
594 checkNotNull(columnKey);
595 Integer columnIndex = columnKeyToIndex.get(columnKey);
596 return (columnIndex == null)
597 ? ImmutableMap.<R, V>of() : new Column(columnIndex);
598 }
599
600 private class Column extends ArrayMap<R, V> {
601 final int columnIndex;
602
603 Column(int columnIndex) {
604 super(rowKeyToIndex);
605 this.columnIndex = columnIndex;
606 }
607
608 @Override
609 String getKeyRole() {
610 return "Row";
611 }
612
613 @Override
614 V getValue(int index) {
615 return at(index, columnIndex);
616 }
617
618 @Override
619 V setValue(int index, V newValue) {
620 return set(index, columnIndex, newValue);
621 }
622 }
623
624
625
626
627
628
629
630 @Override
631 public ImmutableSet<C> columnKeySet() {
632 return columnKeyToIndex.keySet();
633 }
634
635 private transient ColumnMap columnMap;
636
637 @Override
638 public Map<C, Map<R, V>> columnMap() {
639 ColumnMap map = columnMap;
640 return (map == null) ? columnMap = new ColumnMap() : map;
641 }
642
643 private class ColumnMap extends ArrayMap<C, Map<R, V>> {
644 private ColumnMap() {
645 super(columnKeyToIndex);
646 }
647
648 @Override
649 String getKeyRole() {
650 return "Column";
651 }
652
653 @Override
654 Map<R, V> getValue(int index) {
655 return new Column(index);
656 }
657
658 @Override
659 Map<R, V> setValue(int index, Map<R, V> newValue) {
660 throw new UnsupportedOperationException();
661 }
662
663 @Override
664 public Map<R, V> put(C key, Map<R, V> value) {
665 throw new UnsupportedOperationException();
666 }
667 }
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682 @Override
683 public Map<C, V> row(R rowKey) {
684 checkNotNull(rowKey);
685 Integer rowIndex = rowKeyToIndex.get(rowKey);
686 return (rowIndex == null) ? ImmutableMap.<C, V>of() : new Row(rowIndex);
687 }
688
689 private class Row extends ArrayMap<C, V> {
690 final int rowIndex;
691
692 Row(int rowIndex) {
693 super(columnKeyToIndex);
694 this.rowIndex = rowIndex;
695 }
696
697 @Override
698 String getKeyRole() {
699 return "Column";
700 }
701
702 @Override
703 V getValue(int index) {
704 return at(rowIndex, index);
705 }
706
707 @Override
708 V setValue(int index, V newValue) {
709 return set(rowIndex, index, newValue);
710 }
711 }
712
713
714
715
716
717
718
719 @Override
720 public ImmutableSet<R> rowKeySet() {
721 return rowKeyToIndex.keySet();
722 }
723
724 private transient RowMap rowMap;
725
726 @Override
727 public Map<R, Map<C, V>> rowMap() {
728 RowMap map = rowMap;
729 return (map == null) ? rowMap = new RowMap() : map;
730 }
731
732 private class RowMap extends ArrayMap<R, Map<C, V>> {
733 private RowMap() {
734 super(rowKeyToIndex);
735 }
736
737 @Override
738 String getKeyRole() {
739 return "Row";
740 }
741
742 @Override
743 Map<C, V> getValue(int index) {
744 return new Row(index);
745 }
746
747 @Override
748 Map<C, V> setValue(int index, Map<C, V> newValue) {
749 throw new UnsupportedOperationException();
750 }
751
752 @Override
753 public Map<C, V> put(R key, Map<C, V> value) {
754 throw new UnsupportedOperationException();
755 }
756 }
757
758
759
760
761
762
763
764
765
766
767 @Override
768 public Collection<V> values() {
769 return super.values();
770 }
771
772 private static final long serialVersionUID = 0;
773 }